#include "EnumFE.h"

CEnumFormatEtc::CEnumFormatEtc(const LPFORMATETC pFE, int nItems)
{
	m_iCur = 0;
	m_pStrFE = new FORMATETC[nItems];

	if (m_pStrFE && pFE)
    {
		CopyMemory((LPBYTE)m_pStrFE, pFE, sizeof(FORMATETC) * nItems);
		m_cItems = nItems;
    }
	else
    {
		m_cItems = 0;
    }
}


CEnumFormatEtc::~CEnumFormatEtc()
{
	if(m_pStrFE)
		delete [] m_pStrFE;
}

///////////////////////////////////////////////////////////////////////////
//
// IUnknown Implementation
//

/**************************************************************************

   CEnumFormatEtc::QueryInterface()

**************************************************************************/

HRESULT CEnumFormatEtc::QueryInterface(REFIID riid, LPVOID *ppvOut)
{
	*ppvOut = NULL;

	//IUnknown
    if(IsEqualIID(riid, IID_IUnknown))
    {
	   *ppvOut = this;
    }

	//IEnumFORMATETC
    else if(IsEqualIID(riid, IID_IEnumFORMATETC))
    {
		*ppvOut = (IEnumFORMATETC*)this;
    }

    if(*ppvOut)
    {
		(*(LPUNKNOWN*)ppvOut)->AddRef();
		return S_OK;
    }
   return E_NOINTERFACE;
}

/**************************************************************************

   CEnumFormatEtc::AddRef()

**************************************************************************/

ULONG CEnumFormatEtc::AddRef(void)
{
	return CRefCount::AddRef();
}


/**************************************************************************

   CEnumFormatEtc::Release()

**************************************************************************/

ULONG CEnumFormatEtc::Release(void)
{
	return CRefCount::Release();
}

///////////////////////////////////////////////////////////////////////////
//
// IEnumFORMATETC Implementation
//

/**************************************************************************

   CEnumFormatEtc::Next()

**************************************************************************/

HRESULT CEnumFormatEtc::Next(ULONG celt, LPFORMATETC pFE, ULONG *puFetched)
{
	ULONG cReturn = 0L;
	if(celt <= 0 || pFE == NULL || m_iCur >= m_cItems || m_pStrFE == NULL)
		return S_FALSE;

	if(puFetched == NULL && celt != 1)
		return S_FALSE;

	if(puFetched != NULL)
		*puFetched = 0;

	while(m_iCur < m_cItems && celt > 0)
	{
		*pFE++ = m_pStrFE[m_iCur++];
		cReturn++;
		celt--;
    }

	if(NULL != puFetched)
		*puFetched = (cReturn - celt);

	return S_OK;
}

HRESULT CEnumFormatEtc::Skip(ULONG celt)
{
	if((m_iCur + celt) >= m_cItems)
		return S_FALSE;
	m_iCur += celt;
	return S_OK;
}

HRESULT CEnumFormatEtc::Reset(void)
{
	m_iCur = 0;
	return S_OK;
}
               
HRESULT CEnumFormatEtc::Clone(IEnumFORMATETC **ppCloneEnumFormatEtc)
{
	CEnumFormatEtc *newEnum;
	if(NULL == ppCloneEnumFormatEtc)
		return S_FALSE;
	newEnum = new CEnumFormatEtc(m_pStrFE, m_cItems);
	if(newEnum ==NULL)
		return E_OUTOFMEMORY;
	newEnum->AddRef();
	newEnum->m_iCur = m_iCur;
	*ppCloneEnumFormatEtc = newEnum;
	return S_OK;
}
